Skip to main content

TanStack Query

這裡會介紹Next.js在介接API,可以用 TankStack Query來管理頁面上狀態

1. 建立Provider

/src/provider/TanStack.tsx
"use client";import { QueryClient, QueryClientProvider } from "@tanstack/react-query";import { createContext, useContext, useState } from "react";import { apiClient } from "@/lib/axios";const AxiosContext = createContext(apiClient);export function Providers({ children }: { children: React.ReactNode }) {  const [queryClient] = useState(() => new QueryClient());  return (    <AxiosContext.Provider value={apiClient}>      <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>    </AxiosContext.Provider>  );}export const useAxios = () => useContext(AxiosContext);

2. 從 Root Layout 整個包覆應用

/src/Layout.tsx
import type { Metadata } from "next";import localFont from "next/font/local";import "./globals.css";import { Providers } from "@/provider/TanStack";import { Toaster } from "@/components/ui/toaster";const geistSans = localFont({  src: "./fonts/GeistVF.woff",  variable: "--font-geist-sans",  weight: "100 900",});const geistMono = localFont({  src: "./fonts/GeistMonoVF.woff",  variable: "--font-geist-mono",  weight: "100 900",});export const metadata: Metadata = {  title: "聖經APP",  description: "Bible App by create next app",};export default function RootLayout({  children,}: Readonly<{  children: React.ReactNode;}>) {  return (    <html lang="en">      <body        className={`${geistSans.variable} ${geistMono.variable} antialiased`}      >        <Providers>{children}</Providers>        <Toaster />      </body>    </html>  );}

可以從 useQuery這個hook,解構出 dataisLoadingrefetchisFetching

const { data, isLoading, refetch, isFetching } = useQuery<BibleResponse>({  queryKey: ["bibleVerses", book, currentChapter],  queryFn: () => fetchXXXFn(decodeURI(book!), currentChapter.toString()),});
async function fetchXXXFn(
book: string,
chapter: string,
): Promise<BibleResponse> {
const { data } = await axios.get(
`https://bible-api.com/${book}+${chapter}?translation=cuv`,
);
return data;
}

當狀態為 isLoading isFetching 可以將按鈕disabled屬性禁用

<button
onClick={handlePrevious}
disabled={currentChapter <= 1 || isLoading || isFetching}
>
<ArrowBigLeft />
</button>